package evacuator;

import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.proto.ContractNetInitiator;

import java.util.Enumeration;
import java.util.Vector;

import agents.UtilsAgents;
import building.Cell;
import building.InfoGame;

public class ProtocolContractNetInitiator {
	/**
	 * Enter a cell where content the material and the position where I want to
	 * go the civilian.
	 * 
	 * @param Agent
	 * @param Cell
	 */
	public void addBehaviour(Agent agent, building.Cell content, InfoGame game) {
		try {
			// System.out.println("evacuator...."+ agent.getName());
			// System.out.println(" sending" + content.getRow() + "-"
			// +content.getColumn()+"on floor" +content.getFloor() );
			ACLMessage ms = new ACLMessage(ACLMessage.CFP);
			ms.setProtocol(UtilsAgents.CONTRACT_NET);
			ms.setContentObject(content);
			ms.setSender(agent.getAID());
			ms = FindReceivers(agent, ms, content, game);
			agent.addBehaviour(new ProtocolContractNetInit(agent, ms));
		} catch (Exception e) {
			System.err.println("evacuator behaivour" + e.toString());
		}
	}

	/**
	 * For find all civillians
	 */
	private ACLMessage FindReceivers(Agent agent, ACLMessage msg, Cell content,
			InfoGame game) {
		ServiceDescription sd = new ServiceDescription();
		sd.setType(UtilsAgents.CIVILLIAN_AGENT); // receptors

		DFAgentDescription dfd = new DFAgentDescription();
		dfd.addServices(sd);
		try {
			if (content != null) {
				while (true) {
					SearchConstraints c = new SearchConstraints();
					c.setMaxResults(new Long(10));
					DFAgentDescription[] result = DFService.search(agent, dfd,
							c);
					if (result.length > 0) {
						int i = 0;
						int j = result.length;
						while (i < j) {
							dfd = result[i];
							Cell cellR = agents.UtilsAgents.findAgent(
									dfd.getName(), game);
							if (cellR != null
									&& cellR.getFloor() == content.getFloor() && cellR.getCellType() != cellR.DOOR) {
								System.out.println("evacuator"
										+ agent.getLocalName()
										+ "cella civillian" + cellR.getFloor()
										+ "cella destino" + content.getFloor());
								System.out.println(agent.getName()
										+ "envia messagio a " + dfd.getName());
								msg.addReceiver(dfd.getName());
							}
							i = i + 1;
						}
						break;
					}
					Thread.sleep(400); /* Each 5 seconds we try to search */
				}
			}
		} catch (Exception fe) {
			fe.printStackTrace();
			System.out.println(agent.getLocalName()
					+ " search with DF is not succeeded because of "
					+ fe.getMessage());
			agent.doDelete();
		}
		return msg;
	}

	public class ProtocolContractNetInit extends ContractNetInitiator {

		private static final long serialVersionUID = 1L;

		public ProtocolContractNetInit(Agent myAgent, ACLMessage msg) {
			super(myAgent, msg);
		}

		/**
		 * Executed when all responses have been collected or when the timeout
		 * is expired.
		 */
		@SuppressWarnings("unchecked")
		protected void handleAllResponses(Vector responses, Vector acceptances) {
			// Evaluate proposals.
			int bestProposal = -1;
			int firstTime = 0;
			ACLMessage accept = null;
			Enumeration e = responses.elements();
			while (e.hasMoreElements()) {
				ACLMessage msg = (ACLMessage) e.nextElement();
				System.out.println(this.myAgent.getLocalName() + "answer by"
						+ msg.getSender());
				if (msg.getPerformative() == ACLMessage.PROPOSE) {

					ACLMessage reply = msg.createReply();
					int temp = -1;
					temp = Integer.parseInt(msg.getContent());
					System.out.println(this.myAgent.getLocalName()
							+ "proposta di" + msg.getSender() + " " + temp);
					if (temp != -1) {
						System.out.println(this.myAgent.getLocalName()
								+ "accepted" + msg.getSender() + " " + temp);
						reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
						acceptances.addElement(reply);

					} else {
						System.out.println("rejected" + msg.getSender() + " "
								+ temp);
						reply.setPerformative(ACLMessage.REJECT_PROPOSAL);
						acceptances.addElement(reply);
					}
				}
			}
		}

		protected void handleNotUnderstood(ACLMessage msg) {
			System.out.println("HandleNoutUnderstood");
		}

		protected void handleRefuse(ACLMessage msg) {
			System.out.println("evacuator handlerefuse" + msg.getSender());
		}

		protected void handleInform(ACLMessage msg) {
			System.out.println("Handleinform");
		}

		protected void handleFailure(ACLMessage msg) {
			System.out.println("Handlefailure");
		}
	}
}